package com.group.voting_system.controller;

import com.group.voting_system.entity.Candidate;
import com.group.voting_system.entity.User;
import com.group.voting_system.service.ICandidateService;
import com.group.voting_system.service.IUserService;
import com.group.voting_system.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;

/**
 * @Author: xyf
 * @Date: 2019/4/18 21:46
 */
@Controller
public class MediaController {

    @Value("${localPic.path}")
    String picPath;

    @Value("${localVideo.path}")
    String videoPath;

    @Value("${localQR.path}")
    String QRPath;

    @Value("${localExcel.path}")
    String excelPath;

    @Autowired
    IUserService userService;

    @Autowired
    ICandidateService candidateService;

    //获取图片
    @GetMapping("/pic/{url}")
    public void pic(HttpServletResponse response,
                          @PathVariable String url){

        String fileName = picPath + url + "/pic.jpg";
        File file = new File(fileName);
        if (file.exists()){
            response.setContentType("application/force-download");
            response.addHeader("Content-Disposition",
                    "attachment;fileName=" + url + ".jpg");
            byte[] buffer = new byte[1024];
            FileInputStream in = null;
            BufferedInputStream bin = null;
            OutputStream out = null;
            try {
                in = new FileInputStream(file);
                bin = new BufferedInputStream(in);
                out = response.getOutputStream();
                int i = bin.read(buffer);
                while (i != -1){
                    out.write(buffer, 0, i);
                    i = bin.read(buffer);
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if (bin != null){
                    try {
                        bin.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (in != null){
                    try {
                        in.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    //获取视频
    @GetMapping("/video")
    public void video(HttpServletRequest request,
                      HttpServletResponse response,
                      @RequestParam("videoUrl") String videoUrl,
                      @RequestHeader("Range") String range){
        String fileName = videoPath + videoUrl + "/video.mp4";
        File file = new File(fileName);
        if (file.exists()){
            //开始下载位置
            long startByte = 0;
            //结束下载的位置
            long endByte = file.length() - 1;
            //要下载的长度
            long contentLength = endByte - startByte + 1;

            //拼接请求的Range
            if (!range.equals("") && range != null){
                startByte = Long.parseLong(range.substring(range.indexOf("=") + 1, range.lastIndexOf("-")));
                String endRange = range.substring(range.lastIndexOf("-") + 1);
                endByte = endRange.isEmpty() ? endByte : Long.parseLong(endRange);

                startByte = startByte < 0 ? 0 : startByte;
                endByte = endByte > file.length() - 1 ? file.length() - 1 : endByte;
            }

            //文件名
            String fname = file.getName();
            //文件类型
            String contentType = request.getServletContext().getMimeType(fname);
            //响应头设置
            response.setHeader("Accept-Ranges", "bytes");
            //这里注意状态码为206
            response.setStatus(response.SC_PARTIAL_CONTENT);
            response.setContentType(contentType);
            response.setHeader("Content-Type", contentType);
            response.setHeader("Content-Disposition", "inline;filename=" + fname);
            response.setHeader("Content-Length", String.valueOf(contentLength));

            //Content-Range设置
            //[要下载的开始位置]-[结束位置]/[文件总大小]
            response.setHeader("Content-Range", "bytes " +
                    startByte + "-" + endByte + "/" + file.length());
            BufferedOutputStream out = null;
            RandomAccessFile randomAccessFile = null;
            //数据的总大小
            long size = contentLength;
            try {
                randomAccessFile = new RandomAccessFile(file, "r");
                out = new BufferedOutputStream(response.getOutputStream());
                byte[] buff = new byte[4096];
                int len = 0;
                randomAccessFile.seek(startByte);
                //首先当数据还足够长的时候，要先读取
//                while ((transmitted + len) <= contentLength
//                && (len = randomAccessFile.read(buff)) != -1){
//                    out.write(buff, 0, len);
//                    transmitted += len;
//                }
//                //处理不足4096部分
//                if (transmitted < contentLength){
//                    len = randomAccessFile.read(buff, 0, (int) (contentLength - transmitted));
//                    out.write(buff, 0, len);
//                }
                while ((len = randomAccessFile.read(buff)) != -1 && size > 0) {
                    out.write(buff, 0, (int)(size < len ? size : len));
                    size -= len;
                }

                out.flush();
                response.flushBuffer();
                randomAccessFile.close();
                System.out.println("下载完毕");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (randomAccessFile != null){
                    try {
                        randomAccessFile.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    //获取二维码
    @GetMapping("/qr/{id}")
    public void qrCode(@PathVariable("id") Integer id,
                       HttpServletResponse response){
        //生成二维码至本地，并从本地取出，送入response.output
        String fileName = QRPath + id + ".jpg";
        File file = new File(fileName);
        if (file.exists()){

            response.setContentType("application/force-download");// 设置强制下载不打开
            response.addHeader("Content-Disposition",
                    "attachment;fileName=" + id + ".jpg");// 设置文件名

            byte[] buffer = new byte[1024];
            FileInputStream fis = null;
            BufferedInputStream bis = null;
            try {
                fis = new FileInputStream(file);
                bis = new BufferedInputStream(fis);
                OutputStream out = response.getOutputStream();
                int i = bis.read(buffer);
                while (i != -1){
                    out.write(buffer, 0, i);
                    i = bis.read(buffer);
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (bis != null){
                    try {
                        bis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    //下载Excel表格模板
    @GetMapping("/excel/download")
    public void excelDownload(HttpServletResponse response){
        //生成二维码至本地，并从本地取出，送入response.output
        String fileName = excelPath;
        File file = new File(fileName);
        if (file.exists()){
            // 配置文件下载
            response.setHeader("content-type", "application/octet-stream");
            response.setContentType("application/octet-stream");
            // 下载文件能正常显示中文
            response.addHeader("Content-Disposition",
                    "attachment;fileName=" + excelPath.substring(excelPath.lastIndexOf("/") + 1));// 设置文件名

            byte[] buffer = new byte[1024];
            FileInputStream fis = null;
            BufferedInputStream bis = null;
            try {
                fis = new FileInputStream(file);
                bis = new BufferedInputStream(fis);
                OutputStream out = response.getOutputStream();
                int i = bis.read(buffer);
                while (i != -1){
                    out.write(buffer, 0, i);
                    i = bis.read(buffer);
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (bis != null){
                    try {
                        bis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }


    //上传Excel表格
    @ResponseBody
    @PostMapping("/excel/upload")
    public RestResult excelUpload(MultipartFile file){
        if (file.isEmpty()){
            return ResultUtil.fail("请选择文件");
        }
        List<User> users = ExcelUtil.readExcel(file);
        //为每一个用户设置初始密码为工号
        users.forEach(
                u -> {
                    String encodePass = SecureUtil.encryptBasedDes(u.getJobNumber());
                    u.setPassword(encodePass);
                    u.setRole("user");
                }
        );
        userService.saveBatch(users);
        return ResultUtil.success("导入成功");
    }

    /**
     * 上传候选人的视频和照片信息
     * @param cid 候选人id
     * @param vid 投票事件id
     * @param request 获取多文件
     * @return
     */
    @ResponseBody
    @PostMapping("/media/upload")
    public RestResult revise(@RequestParam("cid") Integer cid,
                             @RequestParam("vid") Integer vid,
                             HttpServletRequest request){

        List<MultipartFile> files = ((MultipartHttpServletRequest)request).getFiles("file");
        MultipartFile file = null;
        BufferedOutputStream out = null;
        String type;
        //先查询这个候选人
        Candidate candidate = candidateService.getCandidateById(cid);

        for (int i = 0; i < files.size(); ++i) {
            file = files.get(i);
            //检测文件的类型
            if (!file.isEmpty()) {



                try {
                    type = FileUtil.detectFileType(new BufferedInputStream(file.getInputStream()));
                    byte[] bytes = file.getBytes();
                    //如果文件是jpg类型
                    if (type.equals("image/jpeg")){
                        File newFile = new File(picPath + candidate.getUser().getJobNumber() + vid);
                        if (!newFile.exists())
                            newFile.mkdirs();
                        out = new BufferedOutputStream(new FileOutputStream(
                                new File(picPath + candidate.getUser().getJobNumber() + vid + "/pic.jpg")));
                        candidate.setPhotoUrl(candidate.getUser().getJobNumber() + vid);
                    } else if (type.equals("video/quicktime")){
                        //如果文件是mp4类型
                        File newFile = new File(videoPath + candidate.getUser().getJobNumber() + vid);
                        if (!newFile.exists())
                            newFile.mkdirs();
                        out = new BufferedOutputStream(new FileOutputStream(
                                new File(videoPath + candidate.getUser().getJobNumber() + vid + "/video.mp4")));
                        candidate.setVideoUrl(candidate.getUser().getJobNumber() + vid);
                    } else {
                        return ResultUtil.fail("上传失败");
                    }
                    out.write(bytes);
                } catch (Exception e) {
                    return ResultUtil.fail("上传失败");
                }finally {
                    try {
                        if (out != null)
                            out.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            } else {
                return ResultUtil.fail("上传的文件为空");
            }
        }

        //写完文件后要更新数据库信息
        boolean b = candidateService.reviseUrlById(candidate);
        if (!b)
            return ResultUtil.fail("上传失败");
        return ResultUtil.success("上传成功");
    }
}
